#include <iostream>
#include <iomanip>
#include "Class.h"


using namespace std;

/**
 * Constructor
 * All members are set to 0.
 */
Class::Class()
{
	m_strName = "";
	m_strDesc = "";
	m_iReqStr = 0;
	m_iReqRfx = 0;
	m_iReqInt = 0;
	m_iReqPsy = 0;
	m_iReqCha = 0;
	m_initHP.mHigh = 0;
	m_initHP.mLow = 0;
	m_initMP.mHigh = 0;
	m_initMP.mLow = 0;
	m_iInitPhysAttack = 0;
	m_iInitPhysDefense = 0;
	m_iInitMagAttack = 0;
	m_iInitMagDefense = 0;
	m_iInitEvasion = 0;
	m_iInitStealth = 0;
	m_iInitPerception = 0;
	m_iInitGold.mHigh = 0;
	m_iInitGold.mLow = 0;
}


/**
 * Destructor
 * All items of the Character are destroyed.
 */
Class::~Class()
{

}


/**
 * operator=
 * Overloaded assigment operator.
 * @param const Class& classToCopy - which is the Class to copy
 * @return Class& - a reference to the copied Class
 *
 */
Class& Class::operator=(const Class& classToCopy)
{
	if (this != &classToCopy)
	{
		m_strName = classToCopy.m_strName;
		m_strDesc = classToCopy.m_strDesc;
		m_iReqStr = classToCopy.m_iReqStr;
		m_iReqRfx = classToCopy.m_iReqRfx;
		m_iReqInt = classToCopy.m_iReqInt;
		m_iReqPsy = classToCopy.m_iReqPsy;
		m_iReqCha = classToCopy.m_iReqCha;
		m_initHP.mLow = classToCopy.m_initHP.mLow;
		m_initHP.mHigh = classToCopy.m_initHP.mHigh;
		m_initMP.mLow = classToCopy.m_initMP.mLow;
		m_initMP.mHigh = classToCopy.m_initMP.mHigh;
		m_iInitPhysAttack = classToCopy.m_iInitPhysAttack;
		m_iInitPhysDefense = classToCopy.m_iInitPhysDefense;
		m_iInitMagAttack = classToCopy.m_iInitMagAttack;
		m_iInitMagDefense = classToCopy.m_iInitMagDefense;
		m_iInitEvasion = classToCopy.m_iInitEvasion;
		m_iInitStealth = classToCopy.m_iInitStealth;
		m_iInitPerception = classToCopy.m_iInitPerception;
		m_iInitGold.mLow = classToCopy.m_iInitGold.mLow;
		m_iInitGold.mHigh = classToCopy.m_iInitGold.mHigh;
		for (unsigned int i = 0; i < classToCopy.m_InitEqpt.size(); ++i)
		{
			m_InitEqpt.push_back(classToCopy.m_InitEqpt[i]);
		}
	}
	return *this;
}


/**
 * Set Class description
 * @param std::string desc - a text describing the Player's profession
 * @return void
 */
void Class::setDesc(std::string desc)
{
	m_strDesc = desc;
}


/**
 * Checks if a range of attributes within the requirements
 * @param int iStr - Strength
 * @param int iRfx - Reflexes
 * @param int iInt - Intelligence
 * @param  int iPsy - Psychic
 * @param  int iCha - Charism
 * @return bool - true if everything checks out else false
 */
bool Class::checkRequirements(int iStr, int iRfx, int iInt, int iPsy, int iCha)
{
	if (iStr < m_iReqStr)
		return false;
	if (iRfx < m_iReqRfx)
		return false;
	if (iInt < m_iReqInt)
		return false;
	if (iPsy < m_iReqPsy)
		return false;
	if (iCha < m_iReqCha)
		return false;
	return true;
}


/**
 * Gets the name of the Class
 * @param void
 * @return string - returns the name of the Class
 */
string Class::getName()
{
	return m_strName;
}


/**
 * Returns a random number of Health Points for a Class
 * @param void
 * @return int - returns Health Points
 */
int Class::getInitHP()
{
	return (Random(m_initHP.mLow, m_initHP.mHigh));
}


/**
 * Returns a random number of Magic Points for a Class
 * @param void
 * @return int - returns Magic Points
 */
int Class::getInitMP()
{
	return (Random(m_initMP.mLow, m_initMP.mHigh));
}


/**
 * Returns initial attack for a Class
 * @param void
 * @return int - returns Attack
 */
int Class::getInitPhysAttack()
{
	return m_iInitPhysAttack;
}


/**
 * Returns initial defense for a Class
 * @param void
 * @return int - returns defense points
 */
int Class::getInitPhysDefense()
{
	return m_iInitPhysDefense;
}


/**
 * Returns initial magical attack for a Class
 * @param void
 * @return int - returns magical attack
 */
int Class::getInitMagAttack()
{
	return m_iInitMagAttack;
}


/**
 * Returns initial magical defense for a Class
 * @param void
 * @return int - returns magical attack
 */
int Class::getInitMagDefense()
{
	return m_iInitMagDefense;
}


/**
 * Returns initial evasion for a Class
 * @param void
 * @return int - returns evasion
 */
int Class::getInitEvasion()
{
	return m_iInitEvasion;
}


/**
 * Returns initial stealth for a Class
 * @param void
 * @return int - returns stealth
 */
int Class::getInitStealth()
{
	return m_iInitStealth;
}


/**
 * Returns initial perception for a Class
 * @param void
 * @return int - returns perception
 */
int Class::getInitPerception()
{
	return m_iInitPerception;
}


/**
 * Returns a random number of Gold pieces
 * @param void
 * @return int - gold pieces
 */
int Class::getInitGold()
{
	return (Random(m_iInitGold.mHigh, m_iInitGold.mLow));
}


/**
 * Sets the minimum requirement for a Class
 * @param int iStr - Strength
 * @param int iRfx - Reflexes
 * @param int iInt - Intelligence
 * @param  int iPsy - Psychic
 * @param  int iCha - Charism
 * @return void
 */
void Class::setMinimunReq(int iStr, int iRfx, int iInt, int iPsy, int iCha)
{
	m_iReqStr = iStr;
	m_iReqRfx = iRfx;
	m_iReqInt = iInt;
	m_iReqPsy = iPsy;
	m_iReqCha = iCha;
}


/**
 * Sets the range for Health Points and Magic Points
 * @param int iMinHP - lower range of health points
 * @param int iMaxHP - higher range of health points
 * @param int iMinMP - lower range of magic points
 * @param  int iMaxMP - higher range of magic points
 * @return void
 */
void Class::setHPMP(int iMinHP, int iMaxHP, int iMinMP, int iMaxMP)
{
	m_initHP.mLow = iMinHP;
	m_initHP.mHigh = iMaxHP;
	m_initMP.mLow = iMinMP;
	m_initMP.mHigh = iMaxMP;
}


/**
 * Sets the combat attributes for the Class
 * @param int iPhyAtt - Attack
 * @param int iPhysDef - Defense
 * @param int iMagAtt - Magical attack
 * @param  int iMagDef - Magical defense
 * @return void
 */
void Class::setCombatFactors(int iPhyAtt, int iPhysDef, int iMagAtt, int iMagDef)
{
	m_iInitPhysAttack = iPhyAtt;
	m_iInitPhysDefense = iPhysDef;
	m_iInitMagAttack = iMagAtt;
	m_iInitMagDefense = iMagDef;
}


/**
 * Sets the evasion attribute
 * @param int iValue - evasion
 * @return void
 */
void Class::setEvasion(int iValue)
{
	m_iInitEvasion = iValue;
}


/**
 * Sets the Stealth and Perception of a class
 * @param int iStealth
 * @param int iPerception
 * @return void
 */
void Class::setDiscretion(int iStealth, int iPerception)
{
	m_iInitStealth = iStealth;
	m_iInitPerception = iPerception;
}


/**
 * Sets the Range for the initial gold amount of a Character
 * @param int iMinGold - lower range of the initial gold amount
 * @param int iMaxGold - higher range of the initial gold amount
 * @return void
 */
void Class::setGold(int iMinGold, int iMaxGold)
{
	m_iInitGold.mLow = iMinGold;
	m_iInitGold.mHigh = iMaxGold;
}


/**
 * Adds an Items as an initial equipment
 * @param std::string strItem - name of the Item
 * @return void
 */
void Class::addItem(std::string strItem)
{
	m_InitEqpt.push_back(strItem);
}


/**
 * Sets the name of the class
 * @param std::string name - name of the Class
 * @return void
 */
void Class::setName(std::string name)
{
	m_strName = name;
}


/**
 * Prints out the Class specification
 * @param void
 * @return void
 */
void Class::print()
{
	cout << endl;
	cout << ".oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo" << endl;
	cout << "|" << endl;
	cout << "| Name: " << m_strName << endl;
	cout << "O______________________________O" << endl;
	cout << "o [Minimum Requirements]       o" << endl;
	cout << ". Strength: \t\t" << setw(2) << m_iReqStr << setw(6) << setfill(' ') << "." << endl;
	cout << "o Reflexes: \t\t" << setw(2) << m_iReqRfx << setw(6) << setfill(' ') << "o" << endl;
	cout << "O Intelligence: \t" << setw(2) << m_iReqInt << setw(6) << setfill(' ') << "O" << endl;
	cout << "o Psychic: \t\t" << setw(2) << m_iReqPsy << setw(6) << setfill(' ') << "o" << endl;
	cout << ". Charisma: \t\t" << setw(2) << m_iReqCha << setw(6) << setfill(' ') << "." << endl;
	cout << "o______________________________O" << endl;
	cout << "O HP: \t\t\t" << setw(2) << m_initHP.mLow << "-" << setw(2) << m_initHP.mHigh << setw(3) << setfill(' ') << "o" << endl;
	cout << "O MP: \t\t\t" << setw(2) << m_initMP.mLow << "-" << setw(2) << m_initMP.mHigh << setw(3) << setfill(' ') << "O" << endl;
	cout << ".______________________________." << endl;
	cout << "o [Initial Combat Attributes]  o" << endl;
	cout << "O Physical Attack: \t" << setw(2) << m_iInitPhysAttack << setw(6) << setfill(' ') << "O" << endl;
	cout << "o Physical Defense: \t" << setw(2) << m_iInitPhysDefense << setw(6) << setfill(' ') << "o" << endl;
	cout << ". Magical Attack: \t" << setw(2) << m_iInitMagAttack << setw(6) << setfill(' ') << "." << endl;
	cout << "o Magical Defense: \t" << setw(2) << m_iInitMagDefense << setw(6) << setfill(' ') << "o" << endl;
	cout << "O Evasion: \t\t" << setw(2) << m_iInitEvasion << setw(6) << setfill(' ') << "O" << endl;
	cout << "o______________________________o" << endl;
	cout << "o [Initial Discretion Attr.]   o" << endl;
	cout << "O Stealth: \t" << setw(2) << m_iInitStealth << setw(6) << setfill(' ') << "O" << endl;
	cout << "o Perception: \t" << setw(2) << m_iInitPerception << setw(6) << setfill(' ') << "o" << endl;
	cout << ".______________________________." << endl;
	cout << "o [Initial Equipment]          o" << endl;
	cout << "O Gold: \t\t" << setw(2) << m_iInitGold.mLow << "-" << setw(2) << m_iInitGold.mHigh << setw(3) << setfill(' ') << "O" << endl;
	for (unsigned int i = 0; i < m_InitEqpt.size(); ++i)
	{
		cout << "| - " << m_InitEqpt[i] << endl;
	}
	cout << ".oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo" << endl;
	cout << endl << endl << endl;
}


/**
 * Print our the name of the Class
 * @param void
 * @return void
 */
void Class::printName()
{
	cout << m_strName;
}


/**
 * Print our the description of the Class
 * @param void
 * @return void
 */
void Class::printDesc()
{
	cout << m_strDesc;
}